package com.grantheath.erebus.model 
{
	import com.grantheath.erebus.model.enum.notifications.ErebusInitializationNotifications;
	import com.grantheath.erebus.model.enum.notifications.ErebusAssetLoaderNotifications;
	import com.grantheath.erebus.model.enum.names.ErebusProxyNames;
	import com.grantheath.erebus.model.helpers.ErebusLoadEvent;
	import com.grantheath.erebus.model.interfaces.IErebusAssetNode;
	import com.grantheath.erebus.model.interfaces.IErebusAssetLoader;
	import com.grantheath.erebus.model.interfaces.IErebusAssetLoaderProxy;

	import org.puremvc.as3.patterns.proxy.Proxy;

	/**
	 * @author grantheath
	 */
	public class ErebusAssetLoaderProxy extends Proxy implements IErebusAssetLoaderProxy 
	{
		private var _loadedAsset : Object;

		public function ErebusAssetLoaderProxy()
		{
			super(ErebusProxyNames.ASSET_LOADER_PROXY);
		}

		public function loadAsset(assetNode : IErebusAssetNode) : void
		{
			var assetLoaderClass : Class = assetNode.assetLoaderClass;
			
			assetNode.assetLoader = new assetLoaderClass();
			assetNode.assetLoader.addEventListener(ErebusLoadEvent.LOAD_OPEN, onAssetLoadOpen);
			assetNode.assetLoader.addEventListener(ErebusLoadEvent.LOAD_COMPLETE, onAssetLoadComplete);
			assetNode.assetLoader.addEventListener(ErebusLoadEvent.LOAD_ERROR, onAssetLoadError);
			assetNode.assetLoader.addEventListener(ErebusLoadEvent.LOAD_PROGRESS, onAssetLoadProgress);
			assetNode.assetLoader.loadAsset(assetNode);
		}

		override public function onRegister() : void
		{
			sendNotification(ErebusInitializationNotifications.INITIALIZE_PROXIES);
		}

		public function removeAssetLoadEvents(assetNode : IErebusAssetNode) : void
		{
			if(assetNode.assetLoader) {
				assetNode.assetLoader.removeEventListener(ErebusLoadEvent.LOAD_OPEN, onAssetLoadOpen);
				assetNode.assetLoader.removeEventListener(ErebusLoadEvent.LOAD_COMPLETE, onAssetLoadComplete);
				assetNode.assetLoader.removeEventListener(ErebusLoadEvent.LOAD_ERROR, onAssetLoadError);
				assetNode.assetLoader.removeEventListener(ErebusLoadEvent.LOAD_PROGRESS, onAssetLoadProgress);
			}
		}

		//EVENT LISTENERS
		private function onAssetLoadProgress(event : ErebusLoadEvent) : void
		{
			var loader : IErebusAssetLoader = event.target as IErebusAssetLoader;
			var assetNode : IErebusAssetNode = loader.assetNode;
			
			sendNotification(ErebusAssetLoaderNotifications.ASSET_LOAD_PROGRESS, assetNode);
		}

		private function onAssetLoadError(event : ErebusLoadEvent) : void
		{
			var loader : IErebusAssetLoader = event.target as IErebusAssetLoader;
			var assetNode : IErebusAssetNode = loader.assetNode;
			
			sendNotification(ErebusAssetLoaderNotifications.ASSET_LOAD_ERROR, assetNode);
		}

		private function onAssetLoadComplete(event : ErebusLoadEvent) : void
		{
			var loader : IErebusAssetLoader = event.target as IErebusAssetLoader;
			var assetNode : IErebusAssetNode = loader.assetNode;
			
			assetNode.asset = loader.loadedAsset;
			//for garbage collection
			removeAssetLoadEvents(assetNode);
			assetNode.assetLoader = null;
			loader.assetNode = null;
			sendNotification(ErebusAssetLoaderNotifications.ASSET_LOAD_COMPLETE, assetNode);
		}

		private function onAssetLoadOpen(event : ErebusLoadEvent) : void
		{
			var loader : IErebusAssetLoader = event.target as IErebusAssetLoader;
			var assetNode : IErebusAssetNode = loader.assetNode;
			
			sendNotification(ErebusAssetLoaderNotifications.ASSET_LOAD_OPEN, assetNode);
		}

		//GETTERS AND SETTERS
		public function get loadedAsset() : Object
		{
			return _loadedAsset;
		}

		public function set loadedAsset(loadedAsset : Object) : void
		{
			_loadedAsset = loadedAsset;
		}
	}
}
